package connect4client.core;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import messages.Message;

public class MessageManager implements Runnable{


	public MessageManager(Controller controller){
		this.controller = controller;
		new Thread(this, "MessageManager").start();
	}	
	
	
	public void run() {
		while(true) {				
			try {
				Message message = queue.take();	
				synchronized(this.messageQueue){
					this.messageQueue.offer(message);
				}		
				
				incrementMessageCounter();
				message.setId(this.messageCounter);		
				message.setLastReceivedId(lastReceivedId);
				
				controller.getConnectionController().sendMessage(message);			
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}	
	};
	
	
	public synchronized void reSendAllAfter(int lastMessageId) {			
		synchronized (messageQueue) {
		
			try {
				for (Message message : messageQueue) {
					if (message.getId() > lastMessageId) {
						message.setLastReceivedId(this.lastReceivedId);
						controller.getConnectionController().sendMessageOrFail(message);
					}
				}
			} catch (IOException ex) {
				ex.printStackTrace();
				// Ignore
			}
		}
	}
	

	public synchronized void clearQueueUpTo(int lastMessageId) {		
		while (!messageQueue.isEmpty()) {
			Message message = messageQueue.peek();
			if (message.getId() > lastMessageId)
				break;
		
			messageQueue.remove();
		}
	}


	public synchronized void sendMessage(Message message){		
		try {
			queue.put(message);
		} catch (InterruptedException e) {				
			e.printStackTrace();
		}		
	}


	public synchronized void setLastReceived(int id){
		this.lastReceivedId = id;
	}

	
	public synchronized void incrementMessageCounter(){
		this.messageCounter++;
	}


	public synchronized int getLastReceivedId() {
		return lastReceivedId;
	}

	
	public synchronized int getMessageCounter() {
		return messageCounter;
	}

	
	/**
	 * This method is only called when a loginfailed message 
	 * is received.
	 */
	public void restartMessageCounter(){
		this.messageCounter = -1;
		this.lastReceivedId = -1;
	}
	

	private Controller controller;
	
	// Pending Messages
	private Queue<Message> messageQueue =  new LinkedList<Message>();
	private BlockingQueue<Message> queue = new LinkedBlockingQueue<Message>();

	private int messageCounter = -1;
	private int lastReceivedId = -1;
}

